package com.torry.replay.integration;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.torry.replay.application.exception.ReplayExceptionEnum;
import com.torry.replay.infras.entity.*;
import com.torry.replay.infras.repo.*;
import com.torry.replay.infras.util.NumberUtil;
import com.torry.replay.integration.result.SyncDragonResult;
import com.torry.replay.integration.result.SyncLimitUpResult;
import com.zen.boot.common.util.Preconditions;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author torry.wang
 */
@Component
public class StockApi {

    @Resource
    private TagRepository tagRepository;
    @Resource
    private DragonRepository dragonRepository;
    @Resource
    private SeatRepository seatRepository;
    @Resource
    private LimitUpRepository limitUpRepository;
    @Resource
    private DragonDetailRepository dragonDetailRepository;

    public List<SyncLimitUpResult> getLimitUpList(String date) {
        int count = limitUpRepository.count(new LambdaUpdateWrapper<LimitUpDO>().eq(LimitUpDO::getDate, date));
        Preconditions.ofTrue(count == 0, ReplayExceptionEnum.LIMIT_UP_ALREADY_SYNCED);

        String param = date.replaceAll(" ", "").replaceAll("-", "");
        String url = "https://push2ex.eastmoney.com/getTopicZTPool?ut=7eea3edcaed734bea9cbfc24409ed989&dpt=wz.ztzt&Pageindex=0&pagesize=999&sort=fbt%3Aasc&date=" + param;
        String s = HttpUtil.get(url);
        JSONObject jsonObject = JSON.parseObject(s);
        String realDate = jsonObject.getJSONObject("data").getString("qdate");
        Preconditions.ofTrue(realDate.equals(param), ReplayExceptionEnum.SYNC_LIMIT_UP_FAILED);

        String pool = jsonObject.getJSONObject("data").getString("pool");
        List<JSONObject> list = JSON.parseArray(pool, JSONObject.class);
        List<SyncLimitUpResult> results = list.stream().map(e -> {
            SyncLimitUpResult result = new SyncLimitUpResult();
            result.setDate(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            result.setName(e.getString("n"));
            result.setPrice(NumberUtil.formatBigDecimal(e.getDouble("p") / 1000));

            result.setIncreaseRange(NumberUtil.format(e.getDouble("zdp")));
            result.setMarketValue(NumberUtil.format(e.getDouble("ltsz") / 100000000));
            result.setVolume(NumberUtil.format(e.getDouble("amount") / 100000000));
            result.setSealAmount(NumberUtil.format(e.getDouble("fund") / 100000000));
            result.setTurnoverRate(NumberUtil.format(e.getDouble("hs")));
            String fbt1 = e.getString("fbt");
            String lbt1 = e.getString("lbt");
            if (fbt1.length() < 6) {
                fbt1 = "0" + fbt1;
            }
            if (lbt1.length() < 6) {
                lbt1 = "0" + lbt1;
            }
            LocalTime fbt = LocalTime.parse(fbt1, DateTimeFormatter.ofPattern("HHmmss"));
            LocalTime lbt = LocalTime.parse(lbt1, DateTimeFormatter.ofPattern("HHmmss"));
            result.setLimitTime(fbt);
            result.setLastLimitTime(lbt);
            result.setBombCount(e.getInteger("zbc"));
            result.setContinuousCount(e.getInteger("lbc"));

            JSONObject zttj = e.getJSONObject("zttj");
            result.setStat(zttj.getString("days") + "天" + zttj.getString("ct") + "板");
            String tagName = e.getString("hybk");
            TagDO tag = tagRepository.getOne(new LambdaQueryWrapper<TagDO>().eq(TagDO::getName, tagName));
            if (tag == null) {
                tag = new TagDO();
                tag.setName(tagName);
                tagRepository.save(tag);
            }
            result.setTagName(tagName);
            result.setTagId(tag.getId());

            return result;

        }).collect(Collectors.toList());

        limitUpRepository.saveOrUpdateBatch(results.stream().map(e -> JSON.parseObject(JSON.toJSONString(e), LimitUpDO.class)).collect(Collectors.toList()));
        return results;
    }

    public List<SyncDragonResult> getTodayDragonList(LocalDate date) {

        int count = dragonRepository.count(new LambdaUpdateWrapper<DragonDO>().eq(DragonDO::getDate, date));
        Preconditions.ofTrue(count == 0, ReplayExceptionEnum.DRAGON_ALREADY_SYNCED);
        String url = "https://datacenter-web.eastmoney.com/api/data/v1/get?reportName=RPT_DAILYBILLBOARD_PROFILE&columns=ALL&pageNumber=1&pageSize=500&sortTypes=1&sortColumns=SECURITY_CODE&source=WEB&client=WEB";
        String s = HttpUtil.get(url);
        JSONObject jsonObject = JSON.parseObject(s);
        String data = jsonObject.getJSONObject("result").getString("data");
        List<JSONObject> list = JSON.parseArray(data, JSONObject.class);
        boolean isSameDay = LocalDateTime.parse(list.get(0).getString("TRADE_DATE"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).getDayOfYear() == date.getDayOfYear();
        if (!isSameDay) {
            return Collections.emptyList();
        }
        list = list.stream().filter(e -> !e.getString("SECURITY_NAME_ABBR").contains("ST") && !e.getString("SECURITY_CODE").startsWith("8") && !e.getString("SECURITY_CODE").startsWith("4") && !e.getString("SECURITY_CODE").startsWith("1")).collect(Collectors.toList());
        List<SyncDragonResult> dragons = list.stream().map(e -> {
            String code = e.getString("SECURITY_CODE");
            String name = e.getString("SECURITY_NAME_ABBR");
            Double rate = NumberUtil.format(e.getDouble("CHANGE_RATE"));

            List<SyncDragonResult.DragonDetail> buyList = getDragonDetails(date, code, 1);
            List<SyncDragonResult.DragonDetail> sellList = getDragonDetails(date, code, 2);
            buyList.addAll(sellList);

            Map<Long, String> namesMap = new HashMap<>();
            buyList = buyList.stream().filter(d -> {
                if (namesMap.containsKey(d.getSeatId()) && namesMap.get(d.getSeatId()).equals(d.getBuyAmount() + "-" + d.getSellAmount())) {
                    return false;
                }
                namesMap.put(d.getSeatId(), d.getBuyAmount() + "-" + d.getSellAmount());
                return true;

            }).collect(Collectors.toList());
            SyncDragonResult dragonDO = new SyncDragonResult();
            dragonDO.setDate(date);
            dragonDO.setName(name);
            dragonDO.setRangePercent(rate);
            dragonDO.setDetails(buyList);

            DragonDO dragon = new DragonDO();
            dragon.setDate(date);
            dragon.setName(name);
            dragon.setRangePercent(rate);
            dragonRepository.save(dragon);

            if (CollectionUtils.isNotEmpty(buyList)) {
                List<DragonDetailDO> detailDos = buyList.stream().map(detail -> {
                    DragonDetailDO dragonDetailDO = new DragonDetailDO();
                    dragonDetailDO.setDragonId(dragon.getId());
                    dragonDetailDO.setSeatId(detail.getSeatId());
                    dragonDetailDO.setBuyAmount(detail.getBuyAmount());
                    dragonDetailDO.setSellAmount(detail.getSellAmount());
                    return dragonDetailDO;
                }).collect(Collectors.toList());
                dragonDetailRepository.saveBatch(detailDos);
            }
            return dragonDO;
        }).collect(Collectors.toList());

        return dragons;
    }

    public List<SyncDragonResult.DragonDetail> getDragonDetails(LocalDate date, String code, Integer type) {

        String dateParam = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // type == 1  买榜
        String url = "https://datacenter-web.eastmoney.com/api/data/v1/get?reportName=RPT_BILLBOARD_DAILYDETAILSBUY&columns=ALL&filter=(TRADE_DATE='" + dateParam + "')(SECURITY_CODE=\"" + code + "\")&pageNumber=1&pageSize=50&sortTypes=-1&sortColumns=BUY&source=WEB&client=WEB";
        if (type == 2) {
            // type ==2  卖榜
            url = "https://datacenter-web.eastmoney.com/api/data/v1/get?reportName=RPT_BILLBOARD_DAILYDETAILSSELL&columns=ALL&filter=(TRADE_DATE='" + dateParam + "')(SECURITY_CODE=\"" + code + "\")&pageNumber=1&pageSize=50&sortTypes=-1&sortColumns=SELL&source=WEB&client=WEB";
        }
        String s = HttpUtil.get(url);
        JSONObject jsonObject = JSON.parseObject(s);
        String data = jsonObject.getJSONObject("result").getString("data");
        List<JSONObject> list = JSON.parseArray(data, JSONObject.class);
        return list.stream().map(e -> {
            SyncDragonResult.DragonDetail dragonDetailDO = new SyncDragonResult.DragonDetail();
            String seatName = e.getString("OPERATEDEPT_NAME");
            SeatDO seatDO = seatRepository.getOne(new LambdaQueryWrapper<SeatDO>().eq(SeatDO::getSeatName, seatName));
            if (seatDO == null) {
                seatDO = new SeatDO();
                seatDO.setSeatName(seatName);
                seatRepository.saveOrUpdate(seatDO);
            }
            dragonDetailDO.setSeatId(seatDO.getId());
            dragonDetailDO.setBuyAmount(e.getDouble("BUY") == null ? 0 : NumberUtil.format(e.getDouble("BUY") / 10000));
            dragonDetailDO.setSellAmount(e.getDouble("SELL") == null ? 0 : NumberUtil.format(e.getDouble("SELL") / 10000));
            return dragonDetailDO;
        }).collect(Collectors.toList());
    }
}
